/*=============================================================================
#    The element-comm is a tentative program used to test our ideas.           
#                       Copyright (C)  bgao                                    
#
#     This program is free software; you can redistribute it and/or            
#      modify it under the terms of the GNU General Public License             
#     as published by the Free Software Foundation; either version 2           
#         of the License, or (at your option) any later version.               
#
#     This program is distributed in the hope that it will be useful,          
#    but WITHOUT ANY WARRANTY; without even the implied warranty of           
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            
#             GNU General Public License for more details.                    
#
#    You should have received a copy of the GNU General Public License        
#     along with this program; if not, write to the Free Software             
#      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,             
#                       MA  02110-1301, USA.                                  
#==============================================================================
# $Id: mac_data.c 348 2010-11-29 09:01:16Z bgao $ 
#
# $Author: bgao $ 
#
# $Revision: 348 $ 
#
# $Date: 2010-11-29 17:01:16 +0800 (星期一, 29 十一月 2010) $ 
#
# Description: 
#
=============================================================================*/
/*! @file mac_data.c
 *  @brief This file provides the mac data related functionality
 */
#include "mac.h"

/*! mac data req primitive, which is used to send data through the MAC layer.
 *  @param buf pointer to the structure of sending buffer.
 *  @param req pointer to the structure of data request.
 *  @return return the status of the data request.
 */
int8 mac_data_req(buf_t *buf, mac_data_req_t *req)
{
    mac_hdr_t hdr;
    mac_frm_ctrl_t *ctrl = &hdr.ctrl;
    mac_data_cfm_t cfm;
    int8 ret;
    bool en_ack = 0;
    bool en_indir = 0;

    if (buf == NULL) {
        ret = MAC_INVALID_PARAMETER;
        goto data_req_err_process;
    }

    if (req == NULL) {
        ret = MAC_INVALID_PARAMETER;
        goto data_req_err_process;
    }

    if (req->src.mode == NOT_PRESENT && req->dest.mode == NOT_PRESENT) {
        ret = MAC_INVALID_ADDRESS; 
        goto data_req_err_process;
    }

    /* the spec say, the Frame Version subfield of the Frame Control
     * field should be set to one if the msduLength parameter is 
     * greater than aMaxMACSafePayloadSize.
     * but the Frame Control field is set to 1 when building the data
     * request frame, so ignore it.
     */

    /* Ack request subfield is set in the data request frame. */
    /* GTS is not implemented */
    en_ack = req->opt.ack;
    en_indir = req->opt.indir;

    /* construct frame contrl field */
    ctrl->frm_type = FRM_TYPE_DATA;
    ctrl->en_sec = 0;
    ctrl->frm_pend = 0;
    ctrl->ack = 1;
    ctrl->pan_id_comp = 1;
    ctrl->dest_addr_m = req->dest.mode;
    ctrl->frm_ver = V_2006;
    ctrl->src_addr_m = req->src.mode;

    hdr.dsn = mac_get_dsn();
    hdr.dest_pan_id = req->dest_pan_id;
    hdr.dest_addr.mode = req->dest.mode;
    hdr.dest_addr.a.addr64 = req->dest.a.addr64;
    hdr.src_addr.mode = req->src.mode;
    hdr.src_addr.a.addr64 = req->src.a.addr64;

    ret = mac_gen_hdr(buf, &hdr);

    if (ret != MAC_OK) {
        goto data_req_err_process;
    }

    ret = mac_handle_tx(buf, &(req->dest), en_ack, en_indir, req->handle, hdr.dsn);
    if (ret != MAC_OK) {
        goto data_req_err_process;
    }

    return MAC_OK;
        
data_req_err_process:
    /* TODO confirm */
    cfm.handle = req->handle;
    cfm.status = ret;
    mac_data_cfm(&cfm);

    buf_free(buf);

    return ret;
}

